package dtl

import (
	"encoding/hex"
	"fmt"
	"io"
	"log"
	"strconv"
	"strings"
	"time"
)

type DL64597 struct {
	Start1  byte
	Addr    []byte
	Start2  byte
	Kz      byte
	DataLen byte
	Data    []byte
	Cs      byte
	End     byte
}

func (d *DL64597) Parse(bys []byte) bool {
	Numb := len(bys)
	d.Addr = make([]byte, 6)
	d.Data = make([]byte, 0)
	//检验结尾符号
	for i := 0; i < Numb; i++ {
		if Numb-i < 12 {
			return false
		}
		//log.Printf("bys[%d]=%x", i, bys[i])
		if bys[i] != 0x68 {
			continue
		}
		if bys[i+7] != 0x68 {
			continue
		}
		//找到了数据帧头部
		d.Start1 = 0x68
		d.Addr = bys[i+1 : i+7]
		d.Start2 = 0x68
		d.Kz = bys[i+8]
		d.DataLen = bys[i+9]
		if i+6+int(d.DataLen)+1 > Numb {
			continue
		}
		d.Data = bys[i+10 : i+10+int(d.DataLen)]
		d.Cs = bys[i+10+int(d.DataLen)]
		d.End = bys[i+10+int(d.DataLen)+1]
		if d.End != 0x16 {
			continue
		}
		return true
	}
	return false
}
func (d *DL64597) AddrString() string {
	if len(d.Addr) != 6 {
		return ""
	}
	add := make([]byte, 6)
	for i, x := range d.Addr {
		add[6-i-1] = x
	}
	return hex.EncodeToString(add)
}
func (d *DL64597) ParseAddr(id string) bool {
	addr, err := hex.DecodeString(id)
	if err != nil {
		return false
	}
	if len(addr) != 6 {
		return false
	}
	d.Addr = make([]byte, 6)
	for i, x := range addr {
		d.Addr[6-i-1] = x
	}
	return true
}

func (d *DL64597) GetCS(bys []byte) byte {
	cs := byte(0)
	for _, x := range bys {
		cs += x
	}
	return cs
}

func (d *DL64597) ToBytes() []byte {
	d.Start1 = DtlStart1
	d.End = DtlEnd
	d.Start2 = DtlStart2
	d.DataLen = byte(len(d.Data))
	d.End = DtlEnd
	bys := make([]byte, 0)
	bys = append(bys, d.Start1)
	bys = append(bys, d.Addr...)
	bys = append(bys, d.Start2)
	bys = append(bys, d.Kz)
	bys = append(bys, d.DataLen)
	bys = append(bys, d.Data...)
	cs := d.GetCS(bys)
	bys = append(bys, cs)
	bys = append(bys, d.End)
	return bys
}

func (d *DL64597) GetCommand(meterid string, data string, kz byte) (bys []byte, isok bool, err error) {
	bys = make([]byte, 0)
	d.Kz = kz
	if !d.ParseAddr(meterid) {
		return bys, false, nil
	}
	data2, err := String2DtlData(data)
	if err != nil {
		return bys, false, err
	}
	d.Data = data2
	d.DataLen = byte(len(d.Data))
	bys = d.ToBytes()
	return bys, true, nil
}

func (d *DL64597) UnpakeData() (zl string, data string, bl string) {
	data2 := DtlData2byte(d.Data)
	if len(data2) < 5 {
		return "", "", ""
	}
	ml := data2[0:2]
	tm1 := make([]byte, 2)
	for i, x := range ml {
		tm1[1-i] = x
	}

	va := data2[2:]
	tm2 := make([]byte, len(va))
	for i, x := range va {
		tm2[len(va)-i-1] = x
	}
	zl = hex.EncodeToString(tm1)
	bl = fmt.Sprintf("%d", tm2[0])

	data = hex.EncodeToString(tm2[1:])
	fmt.Println(len(zl)/2, len(data)/2)
	return
}

func (d *DL64597) GetValue(data string, lenght int, xs float64) (ft []float64) {
	ft = []float64{}
	for i := 0; i < len(data); i += lenght {
		if i+lenght > len(data) {
			break
		}
		a := data[i : i+lenght]
		floatValue, err := strconv.ParseFloat(a, 64)
		if err != nil {
			// 处理错误
			fmt.Println("转换错误:", err)
			return
		}
		ft = append(ft, floatValue/xs)
	}
	return ft
}

func (d *DL64597) GetKvi(Meter *Meter, s io.ReadWriteCloser) (err error) {

	err, v := d.GetMeterComandResult(Meter.MeterAddr, "9010", s, 8, 100)
	log.Printf("总有功功率:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.PT = v[0]
	}
	time.Sleep(1000)
	log.Printf("获取电能表数据成功 %#v", Meter)
	// 获取电压
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b611", s, 4, 1)
	log.Printf("电压:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.UV = v[0]
	}
	time.Sleep(1000)
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b612", s, 4, 1)
	log.Printf("电压:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.VV = v[0]
	}
	time.Sleep(1000)
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b613", s, 4, 1)
	log.Printf("电压:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.WV = v[0]
	}
	time.Sleep(1000)
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b621", s, 4, 100)
	log.Printf("电流:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.UI = v[0]
	}
	time.Sleep(1000)
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b622", s, 4, 100)
	log.Printf("电流:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.VI = v[0]
	}
	time.Sleep(1000)
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b623", s, 4, 100)
	log.Printf("电流:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.WI = v[0]
	}
	time.Sleep(1000)
	//功率因数
	err, v = d.GetMeterComandResult(Meter.MeterAddr, "b650", s, 4, 1000)
	log.Printf("功率因数:%f %s", v, err)
	if err == nil && len(v) > 0 {
		Meter.PF = v[0]
		Meter.Uptime = time.Now().Local().Format("2006-01-02 15:04:05")
	}
	return nil

}

func (d *DL64597) GetMeterComandResult(meterid string, comand string, rw io.ReadWriteCloser, lenght int, xs float64) (err error, values []float64) {
	// 发送命令
	err = nil
	values = []float64{}
	cmd, isok, err := d.GetCommand(meterid, comand, 0x01)
	if !isok {
		err = fmt.Errorf("获取命令失败 ")
		return err, values
	}
	_, err = rw.Write(cmd)
	if err != nil {
		return err, values
	}
	bys := make([]byte, 128)

	n, err := rw.Read(bys)
	if n < 1 {
		return fmt.Errorf("读取数据失败:%s", err), values
	}
	s := hex.EncodeToString(bys[:n])
	log.Printf("读取到数据令: %s", s)
	if d.Parse(bys[:n]) {
		zl, da, bl := d.UnpakeData()
		fmt.Println(zl, da, bl)
		if !strings.Contains(zl, comand) {
			log.Printf("命令错误:%s %s", zl, comand)
		}
		ft := d.GetValue(da, lenght, xs)
		return nil, ft
	}
	return fmt.Errorf("解析数据失败:%s", err), values
}

func (d *DL64597) ReadMeterId(Meter *Meter, s io.ReadWriteCloser) (err error) {
	//fe fe fe fe   68 AA AA AA AA AA AA 68 13 00 DF 16
	Readidbytes := []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x68, 0x13, 0x00, 0xdf, 0x16}
	_, err = s.Write(Readidbytes)
	if err != nil {
		return err
	}
	bys := make([]byte, 128)
	n, err := s.Read(bys)
	if n < 1 {
		return fmt.Errorf("读取数据失败:%s", err)
	}
	if d.Parse(bys[:n]) {
		Meter.MeterAddr = d.AddrString()
		Meter.MeterType = "DTL97"
		return nil
	}
	return fmt.Errorf("解析数据失败:%s", err)
}
